import { IAnimateFrame } from "./types"
export class AnimateFrame implements IAnimateFrame {
    id = null; // 动画索引
    duration = Infinity; // 帧数控制
    isActive = false; // 激活控制
    constructor(public fn) { }
    start(duration) {
        if (this.isActive) return;
        this.duration = duration ?? Infinity;
        this.isActive = true;
        return this.animate();
    }
    stop(id = this.id) {
        this.isActive = false;
        cancelAnimationFrame(id);
    }
    animate(timer = 0) {
        if (this.isActive && this.duration-- > 0) {
            this.fn(timer);
            this.id = requestAnimationFrame(this.animate.bind(this));
            return this.id
        }
    }
}

// 贝塞尔曲线用法参考：https://gitee.com/DieHunter/myCode/tree/master/%E5%89%8D%E7%AB%AF%E5%8A%A8%E7%94%BB/js/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF
// 二次贝塞尔
export function quadraticBezier(_x: number, _y: number, t: number) {
    const mt = 1 - t;
    const t2 = t * t;
    const x = 2 * mt * t * _x + t2;
    const y = 2 * mt * t * _y + t2;
    return [x, y];
}

// 三次贝塞尔
export function cubicBezier(_x1: number, _y1: number, _x2: number, _y2: number, t: number) {
    const cx = 3 * _x1;
    const cy = 3 * _y1;
    const bx = 3 * (_x2 - _x1) - cx;
    const by = 3 * (_y2 - _y1) - cy;
    const ax = 1 - cx - bx;
    const ay = 1 - cy - by;
    const x = ax * Math.pow(t, 3) + bx * Math.pow(t, 2) + cx * t;
    const y = ay * Math.pow(t, 3) + by * Math.pow(t, 2) + cy * t;
    return [x, y];
}
// 计算阶乘
export function factorial(n: number) {
    if (n === 0 || n === 1) {
        return 1;
    }
    return n * factorial(n - 1);
}
// 计算组合数
export function combination(n: number, k: number) {
    return factorial(n) / (factorial(k) * factorial(n - k));
}
// N次贝塞尔，x和y坐标使用二阶数组传递
export function NBezier(points: number[][], t: number) {
    const n = points.length - 1;
    const result = [0, 0];
    for (let i = 0; i <= n; i++) {
        const coefficient =
            combination(n, i) * Math.pow(1 - t, n - i) * Math.pow(t, i);
        result[0] += coefficient * points[i][0];
        result[1] += coefficient * points[i][1];
    }
    return result;
}

export default {
    AnimateFrame,
    quadraticBezier,
    cubicBezier,
    factorial,
    combination,
    NBezier,
}